﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using Microsoft.Win32; //to access registry (init openofficeenvironment)
using System.IO; //for Path... (init openofficeenvironment)
using System.Runtime.InteropServices; //for Marshal (init openofficeenvironment)


/* 
* Add all needed CLI namespaces to the current class. 
*/ 
using unoidl.com.sun.star.lang;  
using unoidl.com.sun.star.uno;  
using unoidl.com.sun.star.bridge;  
using unoidl.com.sun.star.frame;



namespace ConsoleApplication1
{
    class OpenOfficeApp
    {
        [DllImport("User32", CharSet=CharSet.Auto, ExactSpelling=true)]
        internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);

        protected void InitOpenOfficeEnvironment()
        {
            string baseKey;
            // OpenOffice being a 32 bit app, its registry location is different in a 64 bit OS  
            if (Marshal.SizeOf(typeof(IntPtr)) == 8)
                baseKey = @"SOFTWARE\Wow6432Node\OpenOffice.org\";
            else
                baseKey = @"SOFTWARE\OpenOffice.org\";

            // Get the URE directory  
            string key = baseKey + @"Layers\URE\1";
            RegistryKey reg = Registry.CurrentUser.OpenSubKey(key);
            if (reg == null) reg = Registry.LocalMachine.OpenSubKey(key);
            string urePath = reg.GetValue("UREINSTALLLOCATION") as string;
            reg.Close();
            urePath = Path.Combine(urePath, "bin");

            // Get the UNO Path  
            key = baseKey + @"UNO\InstallPath";
            reg = Registry.CurrentUser.OpenSubKey(key);
            if (reg == null) reg = Registry.LocalMachine.OpenSubKey(key);
            string unoPath = reg.GetValue(null) as string;
            reg.Close();

            string path;
            path = string.Format("{0};{1}", System.Environment.GetEnvironmentVariable("PATH"), urePath);
            System.Environment.SetEnvironmentVariable("PATH", path);
            System.Environment.SetEnvironmentVariable("UNO_PATH", unoPath);
        }  

        //Define a file name. Change this to an existing path!  
        private static string FileName = @"C:\test.odp";

        [STAThread] static void Main(string[] args)
        {
            XComponent xComponent = null;
            Form1 theform = new Form1();
            Form1 theform2 = new Form1();
            try
            {
                OpenOfficeApp x = new OpenOfficeApp();
                //unoidl.com.sun.star.frame.XFramesSupplier supplier = new XFramesSupplier();
                unoidl.com.sun.star.frame.XFrame oooFrame;
                unoidl.com.sun.star.awt.XWindow oooWindow;
                uno.Any ooohWnd; //window handle.
                System.IntPtr ooohWnd2 = new IntPtr(0);
                System.IntPtr frmhWnd;

                x.InitOpenOfficeEnvironment();
                //Call the bootstrap method to get a new ComponentContext  
                //object. If OpenOffice isn't already started this will  
                //start it and then return the ComponentContext.  
                unoidl.com.sun.star.uno.XComponentContext localContext = uno.util.Bootstrap.bootstrap();

                //Get a new service manager of the MultiServiceFactory type  
                //we need this to get a desktop object and create new CLI  
                //objects.  
                unoidl.com.sun.star.lang.XMultiServiceFactory multiServiceFactory =
                   (unoidl.com.sun.star.lang.XMultiServiceFactory)localContext.getServiceManager();
                //Create a new Desktop instance using our service manager  
                //Notice: We cast our desktop object to XComponent loader  
                //so that we could load or create new documents.  
                XComponentLoader componentLoader = (XComponentLoader)multiServiceFactory.createInstance("com.sun.star.frame.Desktop");
                //Create a new blank writer document using our component  
                //loader object.  
                xComponent = componentLoader.loadComponentFromURL(
                   "private:factory/simpress",    //a blank writer document  
                   "oootestframe", 0,       //into a blank frame named "oootestframe" use no searchflag  
                    //use no additional arguments.  
                    new unoidl.com.sun.star.beans.PropertyValue[0]);

                //Get Interface to Presentation, and save it in variable thepresentation
                unoidl.com.sun.star.presentation.XPresentation thepresentation = ((unoidl.com.sun.star.presentation.XPresentationSupplier)xComponent).getPresentation();

                //Get Enhanced Presentation from thepresentation
                //unoidl.com.sun.star.presentation.XPresentation2 enhancedpresentation = (unoidl.com.sun.star.presentation.XPresentation2)thepresentation;

                // thepresentation.start();
                // unoidl.com.sun.star.presentation.XSlideShowController controller = enhancedpresentation.getController();

                //  controller.AlwaysOnTop = true;

                ((XStorable)xComponent).storeToURL(
                    //Convert the file path into a OpenOffice path  
                   PathConverter(FileName),
                    //no additional arguments  
                    new unoidl.com.sun.star.beans.PropertyValue[0]);

                //   thepresentation.end();

                Console.WriteLine("Your first OpenOffice document is saved!");

                Label xlabel = new Label();
                xlabel.Text = "Test";
                xlabel.Left = 0;
                xlabel.Top = 0;
                theform.Controls.Add(xlabel);
                xlabel.Visible = true;

                //now attempt to take and control openoffice window making it a child to theform  
           
                oooFrame = ((unoidl.com.sun.star.frame.XFramesSupplier)componentLoader).getActiveFrame();

                //oooFrame = oooFrame.findFrame("oootestframe", 55); //55=global, search all frames!

                oooWindow = oooFrame.getContainerWindow();

                //unoidl.com.sun.star.awt.XSystemDependentWindowPeer.getWindowHandle(byte[], short)

                int processid = Process.GetCurrentProcess().Id;
                byte[] oooprocessid = System.BitConverter.GetBytes(processid);

                ooohWnd = ((unoidl.com.sun.star.awt.XSystemDependentWindowPeer)oooWindow).getWindowHandle(oooprocessid, 1);

                //((unoidl.com.sun.star.awt.XWindow)ooohWnd.Value).setVisible(false);

                oooWindow.setVisible(false); //hides OOO window

                //Marshal.WriteIntPtr(ooohWnd2,(IntPtr)ooohWnd.Value);

                ooohWnd2 = new IntPtr((Int32)ooohWnd.Value);

                if (!ooohWnd.hasValue()) throw new System.Exception();

                frmhWnd = theform.Handle;

                //MessageBox.Show(ooohWnd.Type.ToString()); //Type of value in ooohWnd is Int32, need to convert to IntPtr
                MessageBox.Show(ooohWnd.Value.ToString());
                
                SetParent(ooohWnd2, frmhWnd);
                theform.Show(null);
                theform.Invalidate();
                
                //oooWindow.setVisible(true);

                Console.ReadLine();

                ((unoidl.com.sun.star.util.XCloseable)xComponent).close(true); //closes OOO Document.
            }
            catch(System.Exception e)
            {
                theform.Close();
                ((unoidl.com.sun.star.util.XCloseable)xComponent).close(true); //closes OOO Document.
                MessageBox.Show(e.ToString(),e.GetType().ToString());
                //throw e;
            }
        }
        ///  
        /// Convert into OO file format  
        ///  
        ///
        /// The converted file  

        private static string PathConverter(string file)
        {
            try
            {
                file = file.Replace(@"\", "/");
                return "file:///" + file;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }
    }
}
 